iT邦幫忙

2023 iThome 鐵人賽

DAY 27
1
Modern Web

什麼!在網頁上也可以寫遊戲?系列 第 27

[Day 27] 射飛鏢實作篇-計時、計分系統

  • 分享至 

  • xImage
  •  

繼昨天我們完成了遊戲的主畫面,以及開場的倒數動畫之後,今天要來製作遊戲中的計時、計分功能,以及時間到後,會跳回主畫面的功能。

遊戲計時器

在遊戲中計時器究竟該怎麼做呢?接下來我舉例幾個可能的方法:

  1. 直接設置一個等待,等時間到後觸發遊戲結束。
    先來看看這個方法有什麼問題,首先第一點就是我們沒有辦法讀取到現在剩下多久,就像是你用了手機的計時功能,但你按下去的瞬間畫面就黑掉了,直到時間到時才會亮起,在過程之中我們都沒有辦法得知當下剩餘多久,所以這個方法顯然不可行。
  2. 設置一個變數,再設置一個循環事件,讓該變數的值每秒鐘加 1。
    這個辦法似乎可行,不過事件在循環觸發時,假設重複間隔設為 1000 毫秒,但由於系統的關係,真正在運行時,實際上的間隔可能是 1017 毫秒,如此一來等變數加到 60 的時候,現實可能已經經過了 61.02 秒了,且時間越長,誤差就越大,因此這個辦法也不太可行。
    (這個部分我利用了 這個 事件表做驗證,有興趣的人可以看看。)
  3. 紀錄開始時的時間點,之後要讀取時間時再利用當下時間與開始時間相減。
    意思就是你現在看一下時間,並記錄下來,等到明天時再用那時的時間,減去你剛剛紀錄的時間,這樣是不是就可以準確的得到中間經過了多久呢?而且好處是過程中我們可以完全不用理會它,有需要再讀取就好,至於該如何讀取當下的時間呢?讓我們來看看。

事件表提供了一個預設的變數 system,作為一個物件裡面包含了三種屬性:分別是

  • now:裡面儲存了從 1970/01/01 00:00:00 到現在所經過的時間,單位為毫秒,例如 1696989706678,該結果就如同 Javascript 裡的 Date.now() 一樣。
  • time:裡面儲存了從事件表開始執行到當下所經過的時間,單位同樣為毫秒。
  • projectCode:裡面儲存了專案的代碼,例如現在這個專案就是 ironman2023_cook_2

接下來我們就要利用上面的變數來實作剛剛提到的第三點。

在此之前對於今天的介紹,某些部分我就不再一一寫出每個動作、檢查的名字了,我相信可以讀到現在的人,從敘述就可以知道我們要新增哪些東西,但我還是會仔細的介紹每一個步驟的功能、用途。

建立計時器

 

我們先到事件 初始化 中,找到負責 uiRoot建立圖層佈局,建立兩個文字框,一個用來顯示剩餘的時間,另一個用來顯示分數,我設置的結果如上圖,樣式 我只改變了 字體大小 為 36,剩餘時間的物件 ID 為 time_text,放在畫面的左上角,分數則為 score_text,放在畫面的右上角,其中要注意的是如果放在左上角,錨點要設置成 (0,0),右上角則是 (1,0),不然之後改變文字內容時,文字可能會一直左右跳動。

有了顯示文字之後,再新增一個變數用來定義遊戲時間,game_time = 30,代表 30 秒的意思,這樣之後想要改變時間時,只需要改變這個變數即可,其他地方只需要引入,這對於我們未來在擴增、修改功能時,會比較友善。

重置計時器

我們要在遊戲開始倒數前,將計時器的文字框內容重置,因此到事件 點擊開始遊戲,新增動作 更新文字,根據我們新增文字框時的預設文字,以及剛剛新增的變數,文字框 time_text 的文字要改成 時間:{game_time},新增好後將該動作拉到開始倒數之前執行,這樣每次重新遊玩時,文字框的內容就會被自動重置。

接著我們要紀錄開始遊戲時當下的時間,因此到事件 點擊開始遊戲,新增變數 start_time = {system.now},將當下的時間記錄到變數 start_time 裡面,這裡實際上用 nowtime 都可以,但我比較習慣使用 now

由於我們是在倒數結束後才開始,因此紀錄時間的變數一定要放在動畫結束以後。

更新計時器內容

有了文字框和開始時間後,接下來就是要在遊戲中時刻改變文字框內的數字了,先新增一個事件 更新計時文字,由於只有在遊戲中才需要更新計時器的文字,所以新增檢查 比較數字 {game_state} == 2,這樣事件才不會在其他時候一直執行。

然後就是更新計時器內容,但在更新之前我們必須先計算出當下剩餘的時間,而更新文字的動作沒有辦法使用數學式,因此要先經過 儲存全域變數,將計算後的剩餘時間儲存成變數,再將變數帶入更新文字的動作內,讓我們直接看看公式吧!

{game_time} - floor(({system.now} - {start_time}) / 1000)

先經過 ({system.now} - {start_time}) 利用當下時間減去遊戲開始的時間,可以得到經過的時間,但由於單位為毫秒,所以需要再 / 1000 來將其換算為秒,但由於可能會產生小數點,所以利用了 floor(x) 將小數點無條件捨去,最後再將之前定義的遊戲時間減去經過時間,結果就是單位為秒數的剩餘時間了。

將上面的公式以 整數 型別儲存到 {time_left} 裡面後完成,再將文字框 time_text 內的 文字 更新為 時間:{time_left},這樣更新計時器文字的部分就完成了。

時間到結束遊戲

接下來我們要處理時間到的部分,每次更新時間後,我們都要檢查一次時間是否已經結束,因此我們先來新增事件 時間到結束遊戲,並將此事件設為參考事件。

新增檢查 比較數字 {game_time} == floor(({system.now} - {start_time}) / 1000),也就是經過的時間等於遊戲時間。

然後回到事件 更新計時文字,在最後觸發事件 時間到結束遊戲,這樣每次更新完計時器後,都會檢查一次時間到了沒。

而時間到的第一件事,就是先將變數 game_state 設為 1,也就是準備中的意思,總不能一結束的瞬間就切回主畫面吧?這樣會太突兀,而且這時還可以用到昨天的參考事件 顯示倒數文字,讓遊戲在畫面中顯示「時間到」的文字。

顯示完「時間到」後,就要將飛鏢、標靶隱藏起來,並讓主頁面慢慢淡入,隱藏的部分應該很簡單,淡入的部分就是利用 補間動畫透明度 變成 1 而已,忘記設置細節的人,可以回昨天的文章看看~

由於淡入主畫面的關係,所以我們還得 等待 淡入的動畫時間結束,最後就是將 game_state 設回 0 了。

如此一來,計時器,以及重新遊玩的部分就完成了。

計分系統

現在剩下計分了,首先我們會需要一個變數來記錄分數,而在分數改變的時候,畫面上的文字框也要跟著改變,意思是這兩件事情是連在一起的,所以我們可以利用參考事件,將要改變的數值傳入後,存到變數中,同時更新文字框內容。

因此先新增事件 更新分數,並設定為參考事件,設定變數 score = {value},並更新 score_text 的文字為 {score} 分,這樣我們每次改變分數時,只要觸發這個事件就可以同時改變畫面上的文字了!

接下來和計時器相同,我們得先在每次開始遊戲時重置分數,因此回到 點擊開始遊戲,新增觸發事件 更新分數,並且傳入一個區域變數 value = 0,接著把這個動作拉到倒數前和重置計時器的動作排在一起。

最後一個很簡單的部分,那就是到事件 擊中標靶,同樣觸發事件 更新分數,只是這次是 value = {score} + 1,這樣子就可以在每次擊中標靶後讓分數加 1 了。

CG 範例事件表

總結

今天我們完成了遊戲中的計時、計分系統,而且也能夠重新遊玩,至此為止,遊戲可以說是大致已經完成了,剩下最後一個部分,也就是上傳遊戲分數製作排行榜的部分,但這個部分我們曾經教過,所以明天我會快速的帶過這個部分,並將專案製作成一個遊戲成品囉~


上一篇
[Day 26] 射飛鏢實作篇-主畫面製作、定義遊戲狀態、倒數文字動畫
下一篇
[Day 28] 射飛鏢實作篇-設置排行榜、優化遊戲、製作/發布成品
系列文
什麼!在網頁上也可以寫遊戲?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言